package com.apotik.legenda.util;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.HashAttributeSet;
import javax.print.attribute.standard.PrinterName;
import javax.swing.JOptionPane;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.apotik.legenda.dao.ConfigsDao;
import com.apotik.legenda.dao.ConfigsPrinterDao;
import com.apotik.legenda.dao.PatientsDao;
import com.apotik.legenda.dao.SalesTrxDao;
import com.apotik.legenda.dao.SalesTrxObatDao;
import com.apotik.legenda.model.Config;
import com.apotik.legenda.model.ConfigPrinter;
import com.apotik.legenda.model.Patients;
import com.apotik.legenda.model.SalesTrx;
import com.apotik.legenda.model.Shift;
import com.apotik.legenda.model.User;

public class PrinterUtil {

	//private static String printerName = "Microsoft XPS Document Writer";
	
	private static String printerName(){
		String printerName = "";
		ConfigsDao confDao = new ConfigsDao();
		Criterion crConf = Restrictions.eq("codeConfig", "PRINT_USED");
		List<Config> confList = confDao.loadBy(null, crConf);
		if(confList.size()>0){
			Config conf = confList.get(0);
			printerName = conf.getValue1();
		}
		System.out.println("PrinterName: "+printerName);
		
		return printerName;
	}
	
	public static void printTransaction(SalesTrx st){
		ConfigsPrinterDao dao = new ConfigsPrinterDao();
		Criterion cr1 = Restrictions.eq("useFor", "KWITANSI_RESEP");
		final List<ConfigPrinter> cfList = dao.loadBy(Order.asc("useIndex"), cr1);
		
		PatientsDao patientDao = new PatientsDao();
		Criterion crPatient = Restrictions.eq("salesTrx", st);
		List<Patients> patientList = patientDao.loadBy(null, crPatient);
		Patients patient = patientList.size()>0 ? patientList.get(0):null;
		
		final String noTransaksi = st.getTrxCode()!=null ? st.getTrxCode():"";
		final String doctorName = st.getDoctor()!=null ? st.getDoctor().getFullName():"";
		final String atasNama = patient!=null ? patient.getPatientName():"";
		final String phone = patient!=null ? patient.getPhoneNumber():"";
		
		int amountSalexObat = st.getAmountSalesObat()!=null ? st.getAmountSalesObat().intValue():0;
		int amountRUObat = st.getAmountRU()!=null ? st.getAmountRU().intValue():0;
		int amountMisc = st.getAmountMisc()!=null ? st.getAmountMisc().intValue():0;
		int totalObat = amountSalexObat + amountRUObat + amountMisc;
		
		final String jasaDokter = st.getAmountDokterService()!=null ? AppUtil.formatIDRAlignRight(st.getAmountDokterService().intValue()):"";
		final String obatAmount = totalObat>0 ? AppUtil.formatIDRAlignRight(totalObat):"";
		final String tindakan = st.getAmountMedicalTreatment()!=null ? AppUtil.formatIDRAlignRight(st.getAmountMedicalTreatment().intValue()):"";
		final String labKlinik = st.getAmountLabService()!=null ? AppUtil.formatIDRAlignRight(st.getAmountLabService().intValue()):"";
		final String administrasi = st.getAmountAdministration()!=null ? AppUtil.formatIDRAlignRight(st.getAmountAdministration().intValue()):"";
		final String total = st.getAmountTrx()!=null ? AppUtil.formatIDRAlignRight(st.getAmountTrx().intValue()):"0";
		
		final String terbilang = AppUtil.convertNumberToTerbilang(new Double(total))+" rupiah";
		final String petugas = st.getCreatedBy().getFullName();
		
		HashAttributeSet attributes = new HashAttributeSet();
        attributes.add(new PrinterName(printerName(), null));
        DocFlavor format = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
        PrintService[] services = PrintServiceLookup.lookupPrintServices(format, attributes);
        System.out.println("service: "+services.length);
        
        if (services.length > 0) {
        	 Doc doc = new SimpleDoc(new Printable() {
				@Override
				public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
					if (pageIndex==0) {
						Graphics2D g2d = (Graphics2D)g;
				        g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
				        //int x = (int) pageFormat.getImageableX();
				        //int y = (int) pageFormat.getImageableY();
						
				        for(ConfigPrinter cp: cfList){
				        	String strValue = cp.getStringValue();
				        	if(cp.getUseIndex()==5){
				        		strValue = cp.getStringValue()+" "+noTransaksi;
				        	}else if(cp.getUseIndex()==6){
				        		strValue = cp.getStringValue()+" "+CalendarUtil.calIndonesia_DD_MMM_YYYY();
				        	}else if(cp.getUseIndex()==8){
				        		strValue = cp.getStringValue()+" "+atasNama;
				        	}else if(cp.getUseIndex()==10){
				        		strValue = cp.getStringValue()+" "+doctorName;
				        	}else if(cp.getUseIndex()==12){
				        		strValue = cp.getStringValue();
				        	}else if(cp.getUseIndex()==14){
				        		strValue = cp.getStringValue();
				        	}else if(cp.getUseIndex()==16){
				        		strValue = cp.getStringValue();
				        	}else if(cp.getUseIndex()==18){
				        		strValue = cp.getStringValue()+" "+phone;
				        	}else if(cp.getUseIndex()==20){
				        		strValue = cp.getStringValue();
				        	}else if(cp.getUseIndex()==23){
				        		strValue = jasaDokter;
				        	}else if(cp.getUseIndex()==26){
				        		strValue = obatAmount;
				        	}else if(cp.getUseIndex()==29){
				        		strValue = tindakan;
				        	}else if(cp.getUseIndex()==32){
				        		strValue = labKlinik;
				        	}else if(cp.getUseIndex()==35){
				        		strValue = administrasi;
				        	}else if(cp.getUseIndex()==39){
				        		strValue = total;
				        	}else if(cp.getUseIndex()==41){
				        		strValue = terbilang.toUpperCase();
				        	}else if(cp.getUseIndex()==42){
				        		strValue = cp.getStringValue();
				        	}else if(cp.getUseIndex()==43){
				        		strValue = petugas;
				        	}
				        	
				        	g.setFont(new Font(cp.getFontName(), cp.getFontStyle(), cp.getFontSize()));
							g.drawString(strValue, cp.getStringX(), cp.getStringY());
				        }
						
						return PAGE_EXISTS;
					}else{
						return NO_SUCH_PAGE;
					}
				}
				
        	 }, format, null);
        	 try {
                 services[0].createPrintJob().print(doc, null);
             } catch (PrintException ex) {
                 ex.printStackTrace();
             }
        }
	}
	
	public static void printerLaporanTutupKasir(User selectedCashier, User closeUser, Shift shift){
		final User _selectedCashier = selectedCashier; 
		final Shift _shift = shift;
		final User _closeUser = closeUser;
		
		ConfigsPrinterDao dao = new ConfigsPrinterDao();
		Criterion cr1 = Restrictions.eq("useFor", "LAPORAN_TUTUP_KASIR");
		final List<ConfigPrinter> cfList = dao.loadBy(Order.asc("useIndex"), cr1);
		
		Calendar startTime = CalendarUtil.calendarNow();
		startTime.set(Calendar.HOUR_OF_DAY, 00);
		startTime.set(Calendar.MINUTE, 00);
		startTime.set(Calendar.SECOND, 00);
		System.out.println("startTime: "+startTime.getTime());
		
		Calendar finishTime = CalendarUtil.calendarNow();
		finishTime.set(Calendar.HOUR_OF_DAY, 23);
		finishTime.set(Calendar.MINUTE, 59);
		finishTime.set(Calendar.SECOND, 59);
		System.out.println("finishTime: "+finishTime.getTime());
		
		SalesTrxDao stDao = new SalesTrxDao();
		Criterion crSt1 = Restrictions.eq("shiftName", shift.getShiftName());
		Criterion crSt2 = Restrictions.eq("paymentStatus", AppUtil.TRANSAKSI_STATUS_BAYAR);
		Criterion crSt3 = Restrictions.between("createdDate", startTime.getTime(), finishTime.getTime());
		Criterion crStTunai = Restrictions.eq("paymentBy", AppUtil.PAYMENT_BY_TUNAI);
		Criterion crStCard = Restrictions.eq("paymentBy", AppUtil.PAYMENT_BY_CARD);
		Criterion crStAsr = Restrictions.eq("paymentBy", AppUtil.PAYMENT_BY_ASRNSI);
		
		int sumAmountScAll = 0;
		int sumAmountScTunai = 0;
		int sumAmountScCard = 0;
		int sumAmountScAsr = 0;
		
		SalesTrxObatDao stoDao = new SalesTrxObatDao();
		
		List<SalesTrx> stAllList = stDao.loadBy(Order.asc("salesTrxId"), crSt1, crSt2, crSt3);
		for(SalesTrx st: stAllList){
			Criterion crSto1 = Restrictions.eq("salesTrx", st);
			BigDecimal sumAmountScBg = stoDao.sum("amountSC", crSto1);
			sumAmountScAll += sumAmountScBg!=null ? sumAmountScBg.intValue():0;
		}
		
		List<SalesTrx> stTunaiList = stDao.loadBy(Order.asc("salesTrxId"), crSt1, crSt2, crSt3, crStTunai);
		for(SalesTrx st: stTunaiList){
			Criterion crSto1 = Restrictions.eq("salesTrx", st);
			BigDecimal sumAmountScBg = stoDao.sum("amountSC", crSto1);
			sumAmountScTunai += sumAmountScBg!=null ? sumAmountScBg.intValue():0;
		}
		
		List<SalesTrx> stCardList = stDao.loadBy(Order.asc("salesTrxId"), crSt1, crSt2, crSt3, crStCard);
		for(SalesTrx st: stCardList){
			Criterion crSto1 = Restrictions.eq("salesTrx", st);
			BigDecimal sumAmountScBg = stoDao.sum("amountSC", crSto1);
			sumAmountScCard += sumAmountScBg!=null ? sumAmountScBg.intValue():0;
		}
		
		List<SalesTrx> stAsrList = stDao.loadBy(Order.asc("salesTrxId"), crSt1, crSt2, crSt3, crStAsr);
		for(SalesTrx st: stAsrList){
			Criterion crSto1 = Restrictions.eq("salesTrx", st);
			BigDecimal sumAmountScBg = stoDao.sum("amountSC", crSto1);
			sumAmountScAsr += sumAmountScBg!=null ? sumAmountScBg.intValue():0;
		}
		
		
		BigDecimal sumSalesTrxObatBg = stDao.sum("amountSalesObat", crSt1, crSt2, crSt3);
		BigDecimal sumMiscBg = stDao.sum("amountMisc", crSt1, crSt2, crSt3);
		BigDecimal sumRUBg = stDao.sum("amountRU", crSt1, crSt2, crSt3);
		BigDecimal sumDokterBg = stDao.sum("amountDokterService", crSt1, crSt2, crSt3);
		BigDecimal sumTindakBg = stDao.sum("amountMedicalTreatment", crSt1, crSt2, crSt3);
		BigDecimal sumLabBg = stDao.sum("amountLabService", crSt1, crSt2, crSt3);
		BigDecimal sumAdmBg = stDao.sum("amountAdministration", crSt1, crSt2, crSt3);
		BigDecimal sumDiscountBg = stDao.sum("amountObatDiscount", crSt1, crSt2, crSt3);
		BigDecimal sumRefundBg = stDao.sum("amountRefund", crSt1, crSt2, crSt3);
		BigDecimal sumTunaiBg = stDao.sum("amountTrx", crSt1, crSt2, crSt3, crStTunai); 
		BigDecimal sumCardBg = stDao.sum("amountTrx", crSt1, crSt2, crSt3, crStCard); 
		BigDecimal sumAsrBg = stDao.sum("amountTrx", crSt1, crSt2, crSt3, crStAsr); 
		
		Integer sumSalesTrxObatInt = sumSalesTrxObatBg!=null ? sumSalesTrxObatBg.intValue():0;
		Integer sumMiscInt = sumMiscBg!=null ? sumMiscBg.intValue():0;
		Integer sumRUInt = sumRUBg!=null ? sumRUBg.intValue():0;
		Integer sumDokterInt = sumDokterBg!=null ? sumDokterBg.intValue():0;
		Integer sumTindakInt = sumTindakBg!=null ? sumTindakBg.intValue():0;
		Integer sumLabInt = sumLabBg!=null ? sumLabBg.intValue():0;
		Integer sumAdmInt = sumAdmBg!=null ? sumAdmBg.intValue():0;
		Integer sumDiscountInt = sumDiscountBg!=null ? sumDiscountBg.intValue():0;
		Integer sumRefundInt = sumRefundBg!=null ? sumRefundBg.intValue():0;
		Integer sumTunaiInt = sumTunaiBg!=null ? sumTunaiBg.intValue():0;
		Integer sumCardInt = sumCardBg!=null ? sumCardBg.intValue():0;
		Integer sumAsrInt = sumAsrBg!=null ? sumAsrBg.intValue():0;
		
		final String sumStObatStr = sumSalesTrxObatInt > 0 ? AppUtil.formatIDRAlignRight(sumSalesTrxObatInt):AppUtil.formatIDRAlignRight(0);
		final String sumMiscStr = sumMiscInt > 0 ? AppUtil.formatIDRAlignRight(sumMiscInt):AppUtil.formatIDRAlignRight(0);
		final String sumScStr = sumAmountScAll > 0 ? AppUtil.formatIDRAlignRight(sumAmountScAll):AppUtil.formatIDRAlignRight(0);
		final String sumRuStr = sumRUInt > 0 ? AppUtil.formatIDRAlignRight(sumRUInt):AppUtil.formatIDRAlignRight(0);
		final String sumDokterStr = sumDokterInt > 0 ? AppUtil.formatIDRAlignRight(sumDokterInt):AppUtil.formatIDRAlignRight(0);
		final String sumTindakStr = sumTindakInt > 0 ? AppUtil.formatIDRAlignRight(sumTindakInt):AppUtil.formatIDRAlignRight(0);
		final String sumLabStr = sumLabInt > 0 ? AppUtil.formatIDRAlignRight(sumLabInt):AppUtil.formatIDRAlignRight(0);
		final String sumAdmStr = sumAdmInt > 0 ? AppUtil.formatIDRAlignRight(sumAdmInt):AppUtil.formatIDRAlignRight(0);
		
		final int jumlah1 = sumSalesTrxObatInt + sumMiscInt + sumAmountScAll + sumRUInt + sumDokterInt + sumTindakInt + sumLabInt + sumAdmInt;
		
		final String sumDiscountStr = sumDiscountInt > 0 ? AppUtil.formatIDRAlignRight(sumDiscountInt):AppUtil.formatIDRAlignRight(0);
		final String sumRefundStr = sumRefundInt > 0 ? AppUtil.formatIDRAlignRight(sumRefundInt):AppUtil.formatIDRAlignRight(0);
		
		final int jumlah2 = sumDiscountInt + sumRefundInt;
		
		final String sumTunaiStr = sumTunaiInt > 0 ? AppUtil.formatIDRAlignRight(sumTunaiInt+sumAmountScTunai):AppUtil.formatIDRAlignRight(0);
		final String sumCardStr = sumCardInt > 0 ? AppUtil.formatIDRAlignRight(sumCardInt+sumAmountScCard):AppUtil.formatIDRAlignRight(0);
		final String sumAsrStr = sumAsrInt > 0 ? AppUtil.formatIDRAlignRight(sumAsrInt+sumAmountScAsr):AppUtil.formatIDRAlignRight(0);
		
		final int jumlah3 = sumTunaiInt + sumCardInt + sumAsrInt + sumAmountScTunai + sumAmountScCard + sumAmountScAsr;
		
		HashAttributeSet attributes = new HashAttributeSet();
        attributes.add(new PrinterName(printerName(), null));
        DocFlavor format = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
        PrintService[] services = PrintServiceLookup.lookupPrintServices(format, attributes);
        System.out.println("service: "+services.length);
        if (services.length > 0) {
        	Doc doc = new SimpleDoc(new Printable() {
				@Override
				public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
					if (pageIndex==0) {
						Graphics2D g2d = (Graphics2D)g;
				        g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
				        
				        for(int i=0;i<cfList.size();i++){
				        	ConfigPrinter cp = cfList.get(i);
				        	
				        	String strName = cp.getStringValue();
				        	if(cp.getUseIndex()==5){
				        		strName = CalendarUtil.tanggalIndonesia();
				        	}else if(cp.getUseIndex()==8){
				        		strName = _shift.getShiftName();
				        	}else if(cp.getUseIndex()==11){
				        		strName = _selectedCashier.getFullName();
				        	}else if(cp.getUseIndex()==14){
				        		strName = CalendarUtil.formatDate(_shift.getStartTime(), "HH:mm");
				        	}else if(cp.getUseIndex()==18){
				        		strName = sumStObatStr;
				        	}else if(cp.getUseIndex()==21){
				        		strName = sumMiscStr;
				        	}else if(cp.getUseIndex()==24){
				        		strName = sumScStr;
				        	}else if(cp.getUseIndex()==27){
				        		strName = sumRuStr;
				        	}else if(cp.getUseIndex()==30){
				        		strName = sumDokterStr;
				        	}else if(cp.getUseIndex()==33){
				        		strName = sumTindakStr;
				        	}else if(cp.getUseIndex()==36){
				        		strName = sumLabStr;
				        	}else if(cp.getUseIndex()==39){
				        		strName = sumAdmStr;
				        	}else if(cp.getUseIndex()==42){
				        		strName = AppUtil.formatIDRAlignRight(0);
				        	}else if(cp.getUseIndex()==46){
				        		strName = AppUtil.formatIDRAlignRight(jumlah1);
				        	}else if(cp.getUseIndex()==49){
				        		strName = sumRefundStr;
				        	}else if(cp.getUseIndex()==52){
				        		strName = sumDiscountStr;
				        	}else if(cp.getUseIndex()==56){
				        		strName = AppUtil.formatIDRAlignRight(jumlah2);
				        	}else if(cp.getUseIndex()==59){
				        		strName = AppUtil.formatIDRAlignRight(0);
				        	}else if(cp.getUseIndex()==62){
				        		strName = sumTunaiStr;
				        	}else if(cp.getUseIndex()==65){
				        		strName = sumCardStr;
				        	}else if(cp.getUseIndex()==68){
				        		strName = sumAsrStr;
				        	}else if(cp.getUseIndex()==71){
				        		strName = AppUtil.formatIDRAlignRight(0);
				        	}else if(cp.getUseIndex()==74){
				        		strName = AppUtil.formatIDRAlignRight(0);
				        	}else if(cp.getUseIndex()==79){
				        		strName = AppUtil.formatIDRAlignRight(jumlah3);
				        	}
				        	
				        	else if(cp.getUseIndex()==81){
				        		strName = CalendarUtil.formatDate(CalendarUtil.dateNow(), "dd/MM/yyyy HH:mm:ss");
				        	}else if(cp.getUseIndex()==83){
				        		strName = _closeUser.getFullName();
				        	}
				        	
				        	g.setFont(new Font(cp.getFontName(), cp.getFontStyle(), cp.getFontSize()));
							g.drawString(strName, cp.getStringX(), cp.getStringY());
				        }
				        
						return PAGE_EXISTS;
					}else{
						return NO_SUCH_PAGE;
					}
				}
			}, format, null);
        	try {
                services[0].createPrintJob().print(doc, null);
            } catch (PrintException ex) {
                ex.printStackTrace();
            }
        }
	}
	
	public static void infoPrinterDefault(){
		System.out.println("Menampilkan informasi untuk printer default:");
        PrintService service = PrintServiceLookup.lookupDefaultPrintService();
        System.out.printf("Nama printer: %s\n", service.getName());
        JOptionPane.showMessageDialog(null, "Nama printer: %s\n"+service.getName(), "Info", JOptionPane.INFORMATION_MESSAGE);
        /*System.out.println("Format yang didukung:");
        for (DocFlavor format: service.getSupportedDocFlavors()) {
            System.out.println(format);
        }*/
        
        
	}
	
	public static void infoPrinterAll(){
		System.out.println("\nMenampilkan informasi untuk seluruh printer:");
        PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
        String[] names = new String[services.length];
        for (int i=0;i<services.length;i++) {
        	PrintService service = services[i];
            //System.out.printf("\nNama printer: %s\n", service.getName());
            names[i] = service.getName();
            /*System.out.println("Format yang didukung:");
            for (DocFlavor format: service.getSupportedDocFlavors()) {
                System.out.println(format);
            }*/
        }
        
        if(services.length>0){
        	StringBuffer buffer = new StringBuffer();
        	for(String name: names){
        		buffer.append("--"+name);
        	}
        	JOptionPane.showMessageDialog(null, buffer.toString(), "Info All Printer", JOptionPane.INFORMATION_MESSAGE);
        }
        
	}
	
	
}
